package com.mls.guardian.service;

import com.mls.guardian.ThreadFactoryExetend;
import com.mls.guardian.container.SlaveContainer;
import com.mls.guardian.remoting.client.Client;
import com.mls.guardian.remoting.client.RemoteInvoke;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by jl on 15/10/27.
 */
public class HeartBeat2MService {
    private static final Logger log = LoggerFactory.getLogger(HeartBeat2MService.class);
    private RemoteInvoke remoteInvoke;
    private final ScheduledExecutorService scheduledExecutorService = Executors
            .newSingleThreadScheduledExecutor(new ThreadFactoryExetend("HeartBeat2MServiceScheduledThread"));
    Lock lock = new ReentrantLock();
    private SlaveContainer container;

    public HeartBeat2MService(Client keepaliveMasterClient,SlaveContainer container) throws Exception {
        remoteInvoke = new RemoteInvoke(keepaliveMasterClient);
        this.container = container;
    }

    public void start() throws Exception {
        try{
            ping();
        }catch (Exception e){
            e.printStackTrace();
            log.error("ping error");
        }

        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    boolean isalive = HeartBeat2MService.this.remoteInvoke.keepAaliveIsActive();

                    if(!isalive){
                        HeartBeat2MService.this.reconnectMaster();
                        HeartBeat2MService.this.ping();
                    }else{

                    }
                } catch (Exception e) {
                    log.error("reconnect&ping master error.", e);
                }
            }
        }, 0, 30, TimeUnit.SECONDS);
    }

    public void ping() throws Exception {
        if(lock.tryLock()){
            try {
                this.remoteInvoke.ping();
            }finally {
                lock.unlock();
            }
        }

    }

    public void reconnectMaster() throws Exception {
        remoteInvoke.reconnect();
    }

    public void shutdown(){
        scheduledExecutorService.shutdown();
    }

}
